﻿// Author: Prasanna V. Loganathar
// Project: Edi.Core
// 
// Copyright 2014 Launchark. All Rights Reserved.
// 
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// 
//     http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//  
// Created: 2:06 PM 15-05-2014

namespace Edi.Common.Bootstrap
{
    using System;
    using System.IO;
    using System.IO.Compression;
    using System.Reflection;
    using System.Threading.Tasks;

    using Edi.Common.Infrastructure;

    using SharpLog;

    public class Startup
    {
        private const string UiZipPackage = "UiZipPack";
        private const string DefaultUiAssemblyName = "Edi.UI";
        private const string DefaultUiStartup = "UI/index.html";

        private readonly Assembly uiAssembly;
        private readonly IFileSystem fileSystem;

        public Startup(IFileSystem fileSystem)
        {
            uiAssembly = Assembly.Load(new AssemblyName(DefaultUiAssemblyName));
            this.fileSystem = fileSystem;
        }

        private Stream GetUiFileStream(string fileName)
        {
            var uiFileName = Path.Combine("UI", fileName);
            LogManager.Logger.Debug(uiFileName);
            var dir = Path.GetDirectoryName(uiFileName);
            if (!fileSystem.DirectoryExists(dir))
            {
                fileSystem.CreateDirectory(dir);
            }
            return fileSystem.GetStream(uiFileName, FileAccess.Write, StorageZone.Local);
        }

        public async Task Initialize()
        {
            // TODO: Migrate this to settings.
            // Add a test to make sure resource copy is required.
            {
                fileSystem.DeleteDirectory(Path.Combine(fileSystem.LocalStorePath, "UI"), StorageZone.Local, true);
                LogManager.Log(LogLevel.Debug, "Copying Ui resources");
                try
                {
                    await CopyUiResources();
                }
                catch (Exception ex)
                {
                    LogManager.Log(LogLevel.Error, ex.Message);
                    LogManager.Logger.Debug((e) => ((Exception)e).StackTrace, ex);
                }
            }
        }

        public async Task CopyUiResources()
        {
            var stream = uiAssembly.GetManifestResourceStream(UiZipPackage);
            var archive = new ZipArchive(stream);

            foreach (var zipArchiveEntry in archive.Entries)
            {
                using (var destStream = GetUiFileStream(zipArchiveEntry.FullName))
                {
                    using (var zipStream = zipArchiveEntry.Open())
                    {
                        await zipStream.CopyToAsync(destStream);
                    }
                }
            }
        }

        public Stream GetStartupStream()
        {
            return fileSystem.GetStream(
                Path.Combine(fileSystem.LocalStorePath, DefaultUiStartup),
                FileAccess.Read,
                StorageZone.Local);
        }

        public string GetStartupHtml()
        {
            var stream = GetStartupStream();
            var text = new StreamReader(stream).ReadToEnd();
            stream.Dispose();
            return text;
        }

        public Uri GetStartupUrl()
        {
            return new Uri(Path.Combine(fileSystem.LocalStorePath, DefaultUiStartup));
        }
    }
}